package com.starhub.application.function.biz;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.starhub.application.function.enums.AiFunctionStatusEnum;
import com.starhub.application.interfaces.function.IAiFunctionService;
import com.starhub.common.bean.agent.AiFunction;

import dev.langchain4j.service.tool.ToolExecutor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * AI函数提供者
 * 用于向大模型提供AI函数工具
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AiFunctionProvider {

    private final IAiFunctionService aiFunctionService;

    // 函数缓存，避免频繁查询数据库
    private final Map<String, AiFunction> functionCache = new ConcurrentHashMap<>();

    // 最后一次缓存时间
    private volatile long lastCacheTime = 0;

    // 缓存过期时间（毫秒）
    private static final long CACHE_EXPIRE_TIME = 60 * 1000L;

    public final ToolExecutor toolExecutor = (toolExecutionRequest, memoryId) -> {
        // 获取并解析参数
        Map<String, Object> arguments;
        try {
            arguments =  JSON.parseObject(toolExecutionRequest.arguments());
        } catch (Exception e) {
            arguments =  new HashMap<>();
        }

        return executeFunction(toolExecutionRequest.name(), arguments);
    };

    /**
     * 获取所有启用状态的AI函数列表
     * 
     * @return 函数列表
     */
    public List<AiFunction> getEnabledFunctions() {
        refreshCache();
        return aiFunctionService.list(new LambdaQueryWrapper<AiFunction>()
                .eq(AiFunction::getStatus, AiFunctionStatusEnum.ENABLED.getCode()));
    }

    /**
     * 根据函数名称获取函数
     *
     * @param functionName 函数名称
     * @return 函数对象，如果不存在则返回null
     */
    public AiFunction getFunctionByName(String functionName) {
        refreshCacheIfNeeded();
        return functionCache.get(functionName);
    }

    /**
     * 执行AI函数
     *
     * @param functionName 函数名称
     * @param arguments    函数参数
     * @return 执行结果
     */
    public String executeFunction(String functionName, Map<String, Object> arguments) {
        return aiFunctionService.executeFunction(functionName, arguments);
    }

    /**
     * 检查是否需要刷新缓存
     */
    private void refreshCacheIfNeeded() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastCacheTime > CACHE_EXPIRE_TIME) {
            refreshCache();
        }
    }

    /**
     * 刷新函数缓存
     */
    private synchronized void refreshCache() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastCacheTime <= CACHE_EXPIRE_TIME) {
            return;
        }

        try {
            // 清空缓存
            functionCache.clear();

            // 查询所有启用状态的函数
            List<AiFunction> functions = aiFunctionService.list(new LambdaQueryWrapper<AiFunction>()
                    .eq(AiFunction::getStatus, AiFunctionStatusEnum.ENABLED.getCode()));

            // 更新缓存
            for (AiFunction function : functions) {
                functionCache.put(function.getName(), function);
            }

            // 更新缓存时间
            lastCacheTime = currentTime;

            log.info("AI函数缓存已刷新，共 {} 个函数", functions.size());
        } catch (Exception e) {
            log.error("刷新AI函数缓存失败", e);
        }
    }

    /**
     * 获取可用函数的JSON Schema配置
     * 用于向大模型提供函数定义
     *
     * @return 函数定义列表
     */
    public List<Map<String, Object>> getFunctionSchemas() {
        refreshCacheIfNeeded();

        return functionCache.values().stream()
                .map(function -> {
                    Map<String, Object> schema = new HashMap<>();
                    schema.put("name", function.getName());
                    schema.put("description", function.getDescription());
                    schema.put("parameters", JSON.parse(function.getParameters()));
                    return schema;
                })
                .toList();
    }

    /**
     * 判断函数是否需要确认
     *
     * @param functionName 函数名称
     * @return 是否需要确认
     */
    public boolean needConfirm(String functionName) {
        AiFunction function = getFunctionByName(functionName);
        return function != null && Boolean.TRUE.equals(function.getNeedConfirm());
    }

    /**
     * 判断函数是否触发前端动作
     *
     * @param functionName 函数名称
     * @return 是否触发前端动作
     */
    public boolean triggerFrontend(String functionName) {
        AiFunction function = getFunctionByName(functionName);
        return function != null && Boolean.TRUE.equals(function.getTriggerFrontend());
    }

    /**
     * 获取函数的前端动作类型
     *
     * @param functionName 函数名称
     * @return 前端动作类型
     */
    public String getFrontendAction(String functionName) {
        AiFunction function = getFunctionByName(functionName);
        return function != null ? function.getFrontendAction() : null;
    }

    /**
     * 判断函数执行后是否需要将结果再次给到大模型
     *
     * @param functionName 函数名称
     * @return 是否需要再次给到大模型
     */
    public boolean needRegenerateResult(String functionName) {
        AiFunction function = getFunctionByName(functionName);
        return function != null && Boolean.TRUE.equals(function.getRegenerateResult());
    }

    /**
     * 将函数执行结果再次给到大模型
     * 
     * @param model        聊天语言模型
     * @param userMessage  用户消息
     * @param functionName 函数名称
     * @param arguments    函数参数
     * @param result       函数执行结果
     * @return 模型的新回答
     */
    public String regenerateWithFunctionResult(Object model, String userMessage,
            String functionName, Map<String, Object> arguments,
            String result) {
        return aiFunctionService.regenerateWithFunctionResult(
                (dev.langchain4j.model.chat.ChatLanguageModel) model,
                userMessage, functionName, arguments, result);
    }
}